包名 结绳.安卓

@导入Java("android.view.View")
@导入Java("android.content.Context")
@导入Java("android.graphics.Canvas")
类 画板 : 可视化组件
	@code
	public #<画板>(Context context) {
		super(context);
	}
	
	@Override
	public View onCreateView(Context context) {
		View view = new View(context) {
			@Override
			protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
				super.onMeasure(widthMeasureSpec, heightMeasureSpec);
				#被测量(widthMeasureSpec, heightMeasureSpec);
			}
			
			@Override
			protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
				super.onLayout(changed, left, top, right, bottom);
				#被布局(changed, left, top, right - left, bottom - top);
			}
			
			@Override
			protected void onSizeChanged(int w, int h, int oldw, int oldh) {
				super.onSizeChanged(w, h, oldw, oldh);
				#被改变(w, h, oldw, oldh);
			}
			
			@Override
			protected void onDraw(Canvas canvas) {
				super.onDraw(canvas);
				#绘制操作(canvas);
			}
		};
		return view;
	}
	
	@Override
	public View getView() {
		return view;
	}
	@end

	定义事件 被测量(宽度 : 整数, 高度 : 整数)

	定义事件 被布局(是否变化 : 逻辑型, 左 : 整数, 上 : 整数, 宽度 : 整数, 高度 : 整数)

	定义事件 被改变(新宽度 : 整数, 新高度 : 整数, 旧宽度 : 整数, 旧高度 : 整数)

	定义事件 绘制操作(画布 : 画布对象)
结束 类

@导入Java("java.lang.reflect.Field")
@导入Java("java.util.concurrent.atomic.AtomicInteger")
@导入Java("java.util.concurrent.locks.ReentrantLock")
@导入Java("android.os.SystemClock")
@导入Java("android.view.View")
@导入Java("android.view.Surface")
@导入Java("android.view.SurfaceView")
@导入Java("android.view.SurfaceHolder")
@导入Java("android.content.Context")
@导入Java("android.graphics.Color")
@导入Java("android.graphics.Canvas")
@导入Java("android.graphics.PixelFormat")
@后缀代码("implements SurfaceHolder.Callback, Runnable")
@附加清单(常用清单属性.申请更大内存)
类 表层画板 : 可视化组件
	@code
	private AtomicInteger drawCount;
	private Surface surface;
	private SurfaceView surfaceView;
	private SurfaceHolder surfaceHolder;
	private ReentrantLock surfaceLock;
	private long lastLockTime;
	private long lastFpsTime;
	private int tempFps, fps;
	private Thread thread;
	
	public #<表层画板>(Context context) {
		super(context);
		drawCount = new AtomicInteger();
		surfaceHolder = surfaceView.getHolder();
		if (android.os.Build.VERSION.SDK_INT < 26) {
			surface = surfaceHolder.getSurface();
			try {
				Field mSurfaceLockField = SurfaceView.class.getDeclaredField("mSurfaceLock");
				mSurfaceLockField.setAccessible(true);
				surfaceLock = (ReentrantLock) mSurfaceLockField.get(surfaceView);
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
		surfaceHolder.addCallback(this);
		thread = new Thread(this);
		thread.setPriority(Thread.MAX_PRIORITY);
		thread.start();
	}
	
	@Override
	public SurfaceView onCreateView(Context context) {
		surfaceView = new SurfaceView(context);
		return surfaceView;
	}
	
	@Override
	public SurfaceView getView() {
		return surfaceView;
	}
	
	@Override
	public void run() {
		while (true) {
			if (drawCount.get() <= 0) continue;
			Canvas canvas = null;
			if (surface != null) {
				if (surfaceLock != null) surfaceLock.lock();
				if (drawCount.get() > 0) {
					if (android.os.Build.VERSION.SDK_INT >= 23) {
						canvas = surface.lockHardwareCanvas();
					} else {
						canvas = surface.lockCanvas(null);
					}
				}
			} else {
				canvas = surfaceHolder.lockHardwareCanvas();
			}
			if (canvas != null) {
				lastLockTime = SystemClock.uptimeMillis();
				try {
					#绘制操作(canvas);
					drawCount.decrementAndGet();
					if (SystemClock.uptimeMillis() - lastFpsTime >= 1000) {
						fps = tempFps;
						tempFps = 0;
						drawCount.set(1);
						lastFpsTime = SystemClock.uptimeMillis();
					} else {
						tempFps++;
					}
				} finally {
					if (surface != null) {
						try {
							surface.unlockCanvasAndPost(canvas);
						} finally {
							surfaceLock.unlock();
						}
					} else {
						surfaceHolder.unlockCanvasAndPost(canvas);
					}
				}
				continue;
			}
			if (surface != null) {
				long nowTime = SystemClock.uptimeMillis();
				long nextTime = lastLockTime + 100;
				if (nextTime > nowTime) {
					try {
						Thread.sleep(nextTime - nowTime);
					} catch (Exception e) {
					}
					nowTime = SystemClock.uptimeMillis();
				}
				lastLockTime = nowTime;
				if (surfaceLock != null) surfaceLock.unlock();
			}
		}
	}
	
	@Override
	public void surfaceCreated(SurfaceHolder holder) {
		#被创建();
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
		#被改变(width, height);
		boolean needLock = (surface != null && surfaceLock != null);
		if (needLock) surfaceLock.lock();
		drawCount.set(1);
		if (needLock) surfaceLock.unlock();
	}
	
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) {
		#被销毁();
		boolean needLock = (surface != null && surfaceLock != null);
		if (needLock) surfaceLock.lock();
		drawCount.set(0);
		if (needLock) surfaceLock.unlock();
	}
	@end

	属性读 FPS帧数() : 整数
		code return fps;
	结束 属性

	属性写 常亮显示(是否常亮显示 : 逻辑型)
		code surfaceHolder.setKeepScreenOn(#是否常亮显示);
	结束 属性

	属性写 顶层显示(是否顶层显示 : 逻辑型)
		@code
		surfaceHolder.setFormat(PixelFormat.TRANSPARENT);
		surfaceView.setZOrderOnTop(#是否顶层显示);
		@end
	结束 属性

	属性写 覆盖显示(是否覆盖显示 : 逻辑型)
		code surfaceView.setZOrderMediaOverlay(#是否覆盖显示);
	结束 属性

	方法 刷新画面()
		code drawCount.incrementAndGet();
	结束 方法

	定义事件 绘制操作(画布 : 画布对象)

	定义事件 被创建()

	定义事件 被改变(宽度 : 整数, 高度 : 整数)

	定义事件 被销毁()
结束 类

@指代类("android.graphics.Canvas")
@导入Java("java.util.Map")
@导入Java("java.util.HashMap")
@导入Java("android.graphics.Path")
@导入Java("android.graphics.RectF")
@导入Java("android.graphics.Bitmap")
@导入Java("android.graphics.Canvas")
@禁止创建对象
类 画布对象
	@静态
	变量 默认画笔 : 画笔对象 = 画笔对象.创建画笔()

	@code
	private static Path path;
	private static RectF rectF;
	private static BitmapCacheHandler bitmapCacheHandler;
	
	private static class BitmapCache {
		long lastTime;
		Bitmap bitmap;
	}
	
	private static class BitmapCacheHandler extends Thread {
		private Map<Object, BitmapCache> caches = new HashMap<>();
		private Object lock = new Object();
		
		public BitmapCacheHandler() {
			start();
		}
		
		public BitmapCache getCache(Object key) {
			return caches.get(key);
		}
		
		public void putCache(Object key, BitmapCache cache) {
			synchronized (lock) {
				caches.put(key, cache);
				lock.notify();
			}
		}
		
		@Override
		public void run() {
			while (true) {
				synchronized (lock) {
					if (caches.isEmpty()) {
						try {
							lock.wait();
						} catch (Exception e) {
						}
					}
					for (Map.Entry<Object, BitmapCache> entry : caches.entrySet()) {
						long time = System.currentTimeMillis();
						if (time - entry.getValue().lastTime >= 60000) {
							caches.remove(entry.getKey());
						}
					}
				}
				try {
					Thread.sleep(30000);
				} catch (Exception e) {
				}
			}
		}
	}
	
	private static BitmapCacheHandler getBitmapCacheHandler() {
		if (bitmapCacheHandler == null) {
			synchronized (BitmapCacheHandler.class) {
				if (bitmapCacheHandler == null) {
					bitmapCacheHandler = new BitmapCacheHandler();
				}
			}
		}
		return bitmapCacheHandler;
	}
	@end

	@静态
	方法 创建画布(位图 : 位图对象) : 画布对象
		code return new Canvas(#位图);
	结束 方法

	方法 保存() : 整数
		code return #this.save();
	结束 方法

	方法 恢复()
		code #this.restore();
	结束 方法

	方法 恢复到指定状态(状态 : 整数)
		code #this.restoreToCount(#状态);
	结束 方法

	方法 平移(X坐标 : 单精度小数, Y坐标 : 单精度小数)
		code #this.translate(#X坐标, #Y坐标);
	结束 方法

	方法 旋转(角度 : 单精度小数)
		code #this.rotate(#角度);
	结束 方法

	方法 缩放(X缩放比例 : 单精度小数, Y缩放比例 : 单精度小数)
		code #this.scale(#X缩放比例, #Y缩放比例);
	结束 方法

	方法 填充(颜色值 : 整数)
		code #this.drawColor(#颜色值);
	结束 方法

	方法 画点(X坐标 : 单精度小数, Y坐标 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawPoint(#X坐标, #Y坐标, #画笔);
	结束 方法

	方法 画线(起始X坐标 : 单精度小数, 起始Y坐标 : 单精度小数, 结束X坐标 : 单精度小数, 结束Y坐标 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawLine(#起始X坐标, #起始Y坐标, #结束X坐标, #结束Y坐标, #画笔);
	结束 方法

	方法 画圆(X坐标 : 单精度小数, Y坐标 : 单精度小数, 半径 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawCircle(#X坐标, #Y坐标, #半径, #画笔);
	结束 方法

	方法 画椭圆(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawOval(#X坐标, #Y坐标, #X坐标 + #宽度, #Y坐标 + #高度, #画笔);
	结束 方法

	方法 画矩形(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawRect(#X坐标, #Y坐标, #X坐标 + #宽度, #Y坐标 + #高度, #画笔);
	结束 方法

	方法 画圆角矩形(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, X圆角 : 单精度小数, Y圆角 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawRoundRect(#X坐标, #Y坐标, #X坐标 + #宽度, #Y坐标 + #高度, #X圆角, #Y圆角, #画笔);
	结束 方法

	方法 画圆弧(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, 起始角度 : 单精度小数, 扫描角度 : 单精度小数, 椭圆中心点连接 : 逻辑型 = 真, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawArc(#X坐标, #Y坐标, #X坐标 + #宽度, #Y坐标 + #高度, #起始角度, #扫描角度, #椭圆中心点连接, #画笔);
	结束 方法

	方法 画文字(X坐标 : 单精度小数, Y坐标 : 单精度小数, 文字 : 文本, 画笔 : 画笔对象 = 画布对象.默认画笔)
		code #this.drawText(#文字, #X坐标, #Y坐标 + (#画笔.descent() - #画笔.ascent()), #画笔);
	结束 方法

	方法 画贝塞尔曲线(起始X坐标 : 单精度小数, 起始Y坐标 : 单精度小数, 辅助X坐标 : 单精度小数, 辅助Y坐标 : 单精度小数, 结束X坐标 : 单精度小数, 结束Y坐标 : 单精度小数, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		if (path == null) {
			path = new Path();
		}
		path.moveTo(#起始X坐标, #起始Y坐标);
		path.quadTo(#辅助X坐标, #辅助Y坐标, #结束X坐标, #结束Y坐标);
		#this.drawPath(path, #画笔);
		@end
	结束 方法

	方法 画位图(X坐标 : 单精度小数, Y坐标 : 单精度小数, 位图 : 位图对象, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		if (#位图 == null || #位图.isRecycled()) return;
		#this.drawBitmap(#位图, #X坐标, #Y坐标, #画笔);
		@end
	结束 方法

	方法 画缩放位图(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, 位图 : 位图对象, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		if (#位图 == null || #位图.isRecycled()) return;
		if (rectF == null) {
			rectF = new RectF();
		}
		rectF.left = #X坐标;
		rectF.top = #Y坐标;
		rectF.right = #X坐标 + #宽度;
		rectF.bottom = #Y坐标 + #高度;
		#this.drawBitmap(#位图, null, rectF, #画笔);
		@end
	结束 方法

	方法 画图片(X坐标 : 单精度小数, Y坐标 : 单精度小数, 图片路径 : 文本, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		BitmapCache bitmapCache = getBitmapCacheHandler().getCache(#图片路径);
		if (bitmapCache == null) {
			bitmapCache = new BitmapCache();
			bitmapCache.bitmap = #<位图对象.从文件路径创建位图>(#图片路径);
			bitmapCacheHandler.putCache(#图片路径, bitmapCache);
		}
		bitmapCache.lastTime = System.currentTimeMillis();
		#画位图(#this, #X坐标, #Y坐标, bitmapCache.bitmap, #画笔);
		@end
	结束 方法

	方法 画资源图片(X坐标 : 单精度小数, Y坐标 : 单精度小数, 图片路径 : 文本, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		BitmapCache bitmapCache = getBitmapCacheHandler().getCache(#图片路径);
		if (bitmapCache == null) {
			bitmapCache = new BitmapCache();
			bitmapCache.bitmap = #<位图对象.从资源文件创建位图>(#<安卓应用.取安卓应用>(), #图片路径);
			bitmapCacheHandler.putCache(#图片路径, bitmapCache);
		}
		bitmapCache.lastTime = System.currentTimeMillis();
		#画位图(#this, #X坐标, #Y坐标, bitmapCache.bitmap, #画笔);
		@end
	结束 方法

	方法 画缩放图片(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, 图片路径 : 文本, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		BitmapCache bitmapCache = getBitmapCacheHandler().getCache(#图片路径);
		if (bitmapCache == null) {
			bitmapCache = new BitmapCache();
			bitmapCache.bitmap = #<位图对象.从文件路径创建位图>(#图片路径);
			bitmapCacheHandler.putCache(#图片路径, bitmapCache);
		}
		bitmapCache.lastTime = System.currentTimeMillis();
		#画缩放位图(#this, #X坐标, #Y坐标, #宽度, #高度, bitmapCache.bitmap, #画笔);
		@end
	结束 方法

	方法 画资源缩放图片(X坐标 : 单精度小数, Y坐标 : 单精度小数, 宽度 : 单精度小数, 高度 : 单精度小数, 图片路径 : 文本, 画笔 : 画笔对象 = 画布对象.默认画笔)
		@code
		BitmapCache bitmapCache = getBitmapCacheHandler().getCache(#图片路径);
		if (bitmapCache == null) {
			bitmapCache = new BitmapCache();
			bitmapCache.bitmap = #<位图对象.从资源文件创建位图>(#<安卓应用.取安卓应用>(), #图片路径);
			bitmapCacheHandler.putCache(#图片路径, bitmapCache);
		}
		bitmapCache.lastTime = System.currentTimeMillis();
		#画缩放位图(#this, #X坐标, #Y坐标, #宽度, #高度, bitmapCache.bitmap, #画笔);
		@end
	结束 方法
结束 类

@指代类("android.graphics.Paint")
@导入Java("android.graphics.Paint")
@导入Java("android.graphics.Rect")
@禁止创建对象
类 画笔对象
	@静态
	常量 画笔类型_填充 = 1
	@静态
	常量 画笔类型_描边 = 2
	@静态
	常量 画笔类型_填充和描边 = 3

	@静态
	方法 创建画笔() : 画笔对象
		@code
		Paint paint = new Paint();
		paint.setAntiAlias(true);
		paint.setTextSize(45);
		return paint;
		@end
	结束 方法

	属性读 文字高度() : 单精度小数
		code return #this.descent() - #this.ascent();
	结束 属性

	属性写 抗锯齿(开启抗锯齿 : 逻辑型)
		code #this.setAntiAlias(#开启抗锯齿);
	结束 属性

	属性写 类型(类型 : 整数)
		@code
		switch (#类型) {
			case 1:
				#this.setStyle(Paint.Style.FILL);
				break;
			case 2:
				#this.setStyle(Paint.Style.STROKE);
				break;
			case 3:
				#this.setStyle(Paint.Style.FILL_AND_STROKE);
				break;
		}
		@end
	结束 属性

	属性读 颜色值() : 整数
		code return #this.getColor();
	结束 属性

	属性写 颜色值(颜色值 : 整数)
		code #this.setColor(#颜色值);
	结束 属性

	属性读 文字大小() : 单精度小数
		code return #this.getTextSize();
	结束 属性

	属性写 文字大小(文字大小 : 单精度小数)
		code #this.setTextSize(#文字大小);
	结束 属性

	属性读 宽度() : 单精度小数
		code return #this.getStrokeWidth();
	结束 属性

	属性写 宽度(宽度 : 单精度小数)
		code #this.setStrokeWidth(#宽度);
	结束 属性

	属性读 透明度() : 整数
		code return #this.getAlpha();
	结束 属性

	属性写 透明度(透明度 : 整数)
		code #this.setAlpha(#透明度);
	结束 属性

	属性写 字体(字体 : 字体对象)
		code #this.setTypeface(#字体);
	结束 属性

	方法 测量文字宽度(文字 : 文本) : 单精度小数
		code return #this.measureText(#文字);
	结束 方法

	方法 测量文字界限(文字 : 文本) : 矩形
		@code
		Rect bounds = new Rect();
		#this.getTextBounds(#文字, 0, #文字.length(), bounds);
		return bounds;
		@end
	结束 方法
结束 类

@指代类("android.graphics.Typeface")
@禁止创建对象
类 字体对象
	@静态
	属性读 默认字体() : 字体对象
		code return android.graphics.Typeface.DEFAULT;
	结束 属性

	@静态
	属性读 默认粗体字体() : 字体对象
		code return android.graphics.Typeface.DEFAULT_BOLD;
	结束 属性

	@静态
	属性读 等宽字体() : 字体对象
		code return android.graphics.Typeface.MONOSPACE;
	结束 属性

	@静态
	属性读 衬线字体() : 字体对象
		code return android.graphics.Typeface.SERIF;
	结束 属性

	@静态
	属性读 无衬线字体() : 字体对象
		code return android.graphics.Typeface.SANS_SERIF;
	结束 属性

	@静态
	方法 从资源文件创建字体(窗口环境 : 安卓窗口, 文件名 : 文本) : 字体对象
		code return android.graphics.Typeface.createFromAsset(#窗口环境.getAssets(), #文件名);
	结束 方法

	@静态
	方法 从文件路径创建字体(文件路径 : 文本) : 字体对象
		code return android.graphics.Typeface.createFromFile(#文件路径);
	结束 方法
结束 类